// This is the main DLL file.

#include "stdafx.h"

#include "interop.h"
#include "engine.h"
#include "entity/game.h"
#include "entity/entity.h"
#include "entity/scene.h"
#include "leogame.h"
#include "entity/property.h"
#include "property.h"
#include "input/input.h"
#include "script/script.h"
#include "render/rendersystem.h"

namespace interop {
	using namespace PropertyGridEx;

	void AddProperties(entityfactory_t* i_Creator,entity_t* i_Node,MyPropertyTable^ bag);
	void server::init_system(IntPtr renderwindow_hwnd,IntPtr mainwindow_hwnd)
	{
		fuck_you_all();
		new game_t;
		GAME->init((HWND)renderwindow_hwnd.ToPointer(),(HWND)mainwindow_hwnd.ToPointer());
	}

	void server::update_system()
	{
		GAME->update();
	}

	void server::render_system(bool everything)
	{
		if (everything)
			GAME->voltupdate=true;
		GAME->render(everything);
	}

	void server::exit_system()
	{
		GAME->exit();
		delete GAME;
	}


	void server::CreatePropertyTable(EntityTreeNode^ node)
	{
		node->bag=gcnew MyPropertyTable(nullptr,node->entity);
		AddProperties(node->entity->get_metaobject(),node->entity,node->bag);

	}





void AddProperties(entityfactory_t* i_Creator,entity_t* i_Node,MyPropertyTable^ bag)
		 {
			 String^ crname=gcnew String(i_Creator->get_typename().c_str());
			 if (i_Creator->parent)
			 {
				 AddProperties(i_Creator->parent,i_Node,bag);
			 }

			 node root("root");

			 for (unsigned int n=0; n<i_Creator->get_propertycount(); ++n)
			 {
				 property_t* actpr=i_Creator->get_property(n);
				 root.pushdown(actpr->name.c_str(),actpr);
			 }

			 for (unsigned n=0; n<root.children.size(); ++n)
				 add_property_to_grid(i_Node,root.children[n],crname,bag);
		 }
void CreatePropertyTable(EntityTreeNode^ node)
{
	node->bag=gcnew MyPropertyTable(nullptr,node->entity);
	AddProperties(node->entity->get_metaobject(),node->entity,node->bag);

}
void SetPropertiesRecursive(entityfactory_t* i_Creator,entity_t* i_Node,MyPropertyTable^ bag)
		 {
			 String^ crname=gcnew String(i_Creator->get_typename().c_str());
			 if (i_Creator->parent)
			 {
				 SetPropertiesRecursive(i_Creator->parent,i_Node,bag);
			 }

			 node root("root");

			 for (unsigned int n=0; n<i_Creator->get_propertycount(); ++n)
			 {
				 property_t* actpr=i_Creator->get_property(n);
				 root.pushdown(actpr->name.c_str(),actpr);
//				 root.pushdown("afazom",actpr);
			 }

			 for (unsigned n=0; n<root.children.size(); ++n)
				 set_property_in_grid(i_Node,root.children[n],crname,bag);
		 }

void SetProperties(EntityTreeNode^ node)
{
	SetPropertiesRecursive(node->entity->get_metaobject(),node->entity,node->bag);

}
void SetPropertiesForSelected()
{
	for each (TreeNode^ n in server::SelectedNodes)
	{
		SetProperties((EntityTreeNode^)n);
	}
}











	void fill_rec(entity_t* e, TreeNodeCollection^ nodes)
	{
		EntityTreeNode^ node= gcnew EntityTreeNode(gcnew String(e->name.c_str())+"["+(gcnew String(e->get_metaobject()->get_typename().c_str()))+"]",e);
//		node->Checked=!e->excluded;
		nodes->Add(node);
		CreatePropertyTable(node);
		if (!e->parent)
			node->locked=true;

		for (entity_t* ptr=e->child; ptr; ptr=ptr->next)
			fill_rec(ptr,node->Nodes);
	}
	void server::fill_treeview(TreeNodeCollection^ nodes)
	{
		nodes->Clear();

		if (GAME->scene)
		{
			fill_rec(GAME->scene,nodes);
		}
	}

	void fill_rec_typetree(entityfactory_t* f,TreeNodeCollection^ nodes)
	{
		String^ str=gcnew String(f->get_typename().c_str());

		TreeNode^ newNode = gcnew TreeNode(str);
		nodes->Add(newNode);

		for (entityfactory_t* ptr=f->child; ptr; ptr=ptr->next_sibling)
			fill_rec_typetree(ptr,nodes);

	}

	void server::fill_typetree(TreeNodeCollection^ nodes)
	{
		nodes->Clear();
		fill_rec_typetree(entity_t::get_class_metaobject(),nodes);

	}



	void server::enable_mouse_and_keyboard(bool enable)
	{
		INPSYS->enable_mouse_and_keyboard(enable);
	}

	void server::new_scene()
	{
		if (GAME->scene)
		{
			GAME->scene->exitrecursive();
			GAME->scene->eraserecursive();
		}

		GAME->scene=new scene_t;
		GAME->scene->onload();
	}

	void server::load_scene(String^ file_name)
	{
		char fn[256];
		String_to_string(file_name,fn);
		if (GAME->scene)
		{
			GAME->scene->exitrecursive();
			GAME->scene->eraserecursive();
		}

		GAME->scene=(scene_t*)load_scene_from_file(fn);
// 		if (GAME->scene)
// 			GAME->scene->initrecursive();
	}

	void server::init_scene()
	{
		if (GAME->scene)
			GAME->scene->initrecursive();
	}

	void server::exit_scene()
	{
		if (GAME->scene)
			GAME->scene->exitrecursive();
	}

	TreeNode^ server::new_entity(String^ type_name,TreeNode^ parentNode)
	{
		char tn[256];
		String_to_string(type_name,tn);

		entity_t* e=factorymanager_t::create_object(stringhash::get(tn));
		e->onload();

		String^ str=gcnew String(e->name.c_str())+"["+gcnew String(e->get_metaobject()->get_typename().c_str())+"]";
		EntityTreeNode^ newTreeNode = gcnew EntityTreeNode(str,e);
		newTreeNode->Checked=true;

/*
		TreeNode^ parentNode;
		if (sceneTree->SelectedNodes->Count>0)
			parentNode=sceneTree->SelectedNodes[0];
		else
			parentNode=sceneTree->Nodes[0];

		parentNode->Nodes->Add(newTreeNode);
		parentNode->Expand();
*/

		((EntityTreeNode^)parentNode)->entity->addchild(e);

		if (((EntityTreeNode^)parentNode)->entity->isactive())
		{
			e->initrecursive();
		}

		CreatePropertyTable(newTreeNode);
//		e->is_selected=true;

		return newTreeNode;


		return nullptr;
	}

	void server::save_scene(String^ file_name)
	{
		char fn[256];
		String_to_string(file_name,fn);

		if (GAME->scene)
		{
			GAME->scene->save_to_file(fn);
		}

	}

	void server::delete_entities(List<EntityTreeNode^>^ l)
	{
		for (int n=0; n<l->Count; ++n)
		{
			entity_t* e=l[n]->entity;
			if (e->parent->isactive())
				e->exitrecursive();
			e->parent->removechild(e);
			e->eraserecursive();
			l[n]->Remove();
		}


	}

	void server::reload_scripts()
	{
		String^ datetime;
		char ch[256];
		datetime=System::DateTime::Now.ToString("HH_mm_ss");
		String_to_string(datetime,ch);
		log_t::log(_str("\nBuild started at %s\n----------------------------------------\n",ch));
		SCRIPTMAN->load_scripts(0);
		datetime=System::DateTime::Now.ToString("HH_mm_ss");
		String_to_string(datetime,ch);
		log_t::log(_str("----------------------------------------\nBuild ended at %s\n\n",ch));

		for (entity_t* ptr=GAME->scene; ptr;ptr=ptr->getnextpo(GAME->scene))
			ptr->init_script_function_ids();
	}

	bool server::log_changed()
	{
		return log_t::log_changed();
	}

	String^ server::get_log()
	{
		String^ l=gcnew String(log_t::logstr.c_str());
		return l;
	}

	void server::resize_view()
	{
		if (RSYS)
			RSYS->on_resize();
	}

	void server::debugtexts_enabled(bool on)
	{
		RSYS->textdraw_enabled=on;
	}

	void server::selection_changed(CodersLab::Windows::Controls::NodesCollection^ _SelectedNodes)
	{
		SelectedNodes=_SelectedNodes;
		for (entity_t* ptr=GAME->scene; ptr; ptr=ptr->getnextpo(GAME->scene))
		{
			ptr->selected=false;
		}

		for each (TreeNode^ n in SelectedNodes)
		{
			((EntityTreeNode^)n)->entity->selected=true;
		}
	}


}


